package com.burybell.storage.system;

import com.alibaba.fastjson.JSON;
import com.burybell.storage.domain.Storage;
import com.burybell.storage.system.bean.BurstInputStream;
import com.burybell.storage.utils.IOUtils;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Calendar;
import java.util.Date;
import java.util.Random;

@Slf4j
public class StorageSystem {

    private static final Calendar calendar = Calendar.getInstance();


    private static final Random random = new Random();

    public static BurstInputStream getInputStream(String base, String scene, Integer year, Integer month, Integer day, String sid) {
        File scenePath = new File(base,scene);
        if (scenePath.exists()) {
            File real = new File(scenePath,"/" + year + "/" + month + "/" + day);
            if (real.exists()) {
                return new BurstInputStream(real.getAbsolutePath(),sid);
            } else {
                return null;
            }
        } else {
            return null;
        }
    }

    /**
     * 上传
     * @param base
     * @param scene
     * @param definition
     * @param size
     * @param inputStream
     * @param slice
     * @param buffer
     * @return
     */
    public static Storage upload(String base, String scene, String definition, Long size, InputStream inputStream, int slice, int buffer) {
        Storage storageBean = storageBean(scene, definition, size);
        try {
            File path = getPath(base, scene, storageBean.getYear(), storageBean.getMonth(), storageBean.getDay());
            long[] reckon = reckonSlice(size,slice);
            String sequence = StorageSequence(storageBean);
            for (int i = 0; i < reckon.length; i++) {
                if (i == 0) {
                    FileOutputStream ops = new FileOutputStream(new File(path,String.valueOf(storageBean.getSid())));
                    ops.write(("Content-Length:" + sequence.length() + "\r\n").getBytes(StandardCharsets.UTF_8));
                    ops.write((sequence + "\r\n").getBytes(StandardCharsets.UTF_8));
                    ops.write(("Slice:" + slice + "\r\n\r\n").getBytes(StandardCharsets.UTF_8));
                    IOUtils.copy(inputStream,ops,reckon[i],buffer);
                    ops.close();
                } else {
                    FileOutputStream remain = new FileOutputStream(new File(path, storageBean.getSid() + "." + i));
                    IOUtils.copy(inputStream,remain,reckon[i],buffer);
                    remain.close();
                }
            }
            return storageBean;
        } catch (IOException e) {
            return null;
        }
    }

    private static File mkdir(File file,String name) {
        File ops = new File(file,name);
        if (!ops.exists()) {
            boolean mkdir = ops.mkdir();
            if (!mkdir) {
                log.error("dir error");
            }
        }
        return ops;
    }

    private static String StorageSequence(Storage storage) {
        return JSON.toJSONString(storage);
    }

    public static File getPath(String base,String scene,Integer year,Integer month,Integer day) {
        File scenePath = mkdir(new File(base),scene);
        File yearPath = mkdir(scenePath,String.valueOf(year));
        File mouthPath = mkdir(yearPath,String.valueOf(month));
        return mkdir(mouthPath,String.valueOf(day));
    }

    private static long[] reckonSlice(Long size,int slice){
        long[] slices = new long[slice];
        long max = size/slice;
        for (int i = 0; i < slice; i++) {
            if (i < slice - 1) {
                slices[i] = max;
            } else {
                slices[i] = size - max * (slice - 1);
            }
        }
        return slices;
    }

    /**
     * 获取文件 bean
     * @param scene
     * @param definition
     * @param size
     * @return
     */
    private static Storage storageBean(String scene, String definition, Long size) {
        Storage storageBean = new Storage();
        storageBean.setDefinition(definition);
        storageBean.setScene(scene);
        storageBean.setSize(size);
        calendar.setTime(new Date());
        storageBean.setYear(calendar.get(Calendar.YEAR));
        storageBean.setMonth(calendar.get(Calendar.MONTH) + 1);
        storageBean.setDay(calendar.get(Calendar.DATE));
        storageBean.setSuffix(suffix(definition));
        storageBean.setSid(id());
        return storageBean;
    }

    /**
     * 获取文件后缀
     * @param definition 文件全名
     * @return 文件后缀
     */
    public static String suffix(String definition) {
        int index = definition.lastIndexOf('.');
        return definition.substring(index+1);
    }

    /**
     * 获取id
     * @return
     */
    private static Long id() {
        long id = 0L;
        for (int i = 0; i < 8; i++) {
            int num = random.nextInt(10);
            id = id * 10L + num;
        }
        return id;
    }

}
